/***** BEGIN LICENSE BLOCK *****
 * Version: CPL 1.0/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Common Public
 * License Version 1.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.eclipse.org/legal/cpl-v10.html
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * Copyright (C) 2008 The JRuby Community <www.jruby.org>
 * Copyright (C) 2006 Ola Bini <ola@ologix.com>
 * 
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the CPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the CPL, the GPL or the LGPL.
 ***** END LICENSE BLOCK *****/
package asruby.runtime {

import asruby.lang.RubyModule;
import asruby.parser.StaticScope;
import asruby.runtime.methods.CallConfiguration;
import asruby.runtime.methods.DynamicMethod;

/**
 * MethodFactory is used to generate "invokers" or "method handles" given a target
 * class, method name, and other characteristics. In order to bind methods into
 * Ruby's reified class hierarchy, we need a way to treat individual methods as
 * objects. Implementers of this class provide that functionality.
 */
public class MethodFactory {
    /**
     * A Class[] representing the signature of compiled Ruby method.
     */
    public static var COMPILED_METHOD_PARAMS: Array =  [ThreadContext, IRubyObject, Array, Block];
    
    /**
     * For batched method construction, the logic necessary to bind resulting
     * method objects into a target module/class must be provided as a callback.
     * This interface should be implemented by code calling any batched methods
     * on this MethodFactory.
     */
/*     public interface MethodDefiningCallback {
        public void define(RubyModule targetMetaClass, Method method, DynamicMethod dynamicMethod);
    } */

    /**
     * Based on optional properties, create a new MethodFactory. By default,
     * this will create a code-generation-based InvocationMethodFactory. If
     * security restricts code generation, ReflectionMethodFactory will be used.
     * If we are dumping class definitions, DumpingInvocationMethodFactory will
     * be used. See MethodFactory's static initializer for more details.
     * 
     * @param classLoader The classloader to use for searching for and
     * dynamically loading code.
     * @return A new MethodFactory.
     */
/*     public static function createFactory(classLoader:ClassLoader):MethodFactory{
        if (reflection) return new ReflectionMethodFactory();
        if (dumping) return new DumpingInvocationMethodFactory(dumpingPath, classLoader);

        return new InvocationMethodFactory(classLoader);
    } */
    
    /**
     * Get a new method handle based on the target JRuby-compiled method.
     * Because compiled Ruby methods have additional requirements and
     * characteristics not typically found in Java-based methods, this is
     * provided as a separate way to define such method handles.
     * 
     * @param implementationClass The class to which the method will be bound.
     * @param method The name of the method
     * @param arity The Arity of the method
     * @param visibility The method's visibility on the target type.
     * @param scope The methods static scoping information.
     * @param scriptObject An instace of the target compiled method class.
     * @param callConfig The call configuration to use for this method.
     * @return A new method handle for the target compiled method.
     */
    public function getCompiledMethod(
             implementationClass:RubyModule,  method:String, 
             arity:Arity,  visibility:Visibility,  scope:StaticScope, 
             scriptObject:Object,  callConfig:CallConfiguration):DynamicMethod
    {
    	return null;
    }
    
    /**
     * Based on an annotated Java method object, generate a method handle using
     * the annotation and the target signature. The annotation and signature
     * will be used to dynamically generate the appropriate call logic for the
     * handle.
     * 
     * @param implementationClass The target class or module on which the method
     * will be bound.
     * @param method The java.lang.Method object for the target method.
     * @return A method handle for the target object.
     */
    public function getAnnotatedMethod(implementationClass:RubyModule, method:Function):DynamicMethod {
    	return null;
    }
    
    /**
     * Add all annotated methods on the target Java class to the specified
     * Ruby class using the semantics of getAnnotatedMethod, calling back to
     * the specified callback for each method to allow the caller to bind
     * each method.
     * 
     * @param implementationClass The target class or module on which the method
     * will be bound.
     * @param containingClass The Java class containined annotated methods to
     * be bound.
     * @param callback A callback provided by the caller which handles binding
     * each method.
     */
    public function defineIndexedAnnotatedMethods(
    	implementationClass:RubyModule,  containingClass:Class,  callback:Object):void {
    		
    	}

    /**
     * Use the reflection-based factory.
     */
    private static var reflection: Boolean =  false;
    /**
     * User the dumping-based factory, which generates  files as it runs.
     */
    private static var dumping: Boolean =  false;
    /**
     * The target path for the dumping factory to save the  files.
     */
    private static var dumpingPath: String =  null;
    
    {
        // initialize the static settings to determine which factory to use
       /*  if (Ruby.isSecurityRestricted()) { */
            reflection = true;
        /*} else {
            if (SafePropertyAccessor.getProperty("jruby.reflection") != null && SafePropertyAccessor.getBoolean("jruby.reflection")) {
                reflection = true;
            }
            if (SafePropertyAccessor.getProperty("jruby.dump_invocations") != null) {
                dumping = true;
                dumpingPath = SafePropertyAccessor.getProperty("jruby.dump_invocations");
            }
        } */
    }
}
}